﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace GameStateManagement
{
    class ShrinkingStarSphere : StarSphere
    {
        private static ShrinkingStarSphere shrinkingStarSphere;

        public static float LevelPlanetRadius = 1950f;

        public static float StartSize = 5000f;
        public static Vector3 StartColor = Color.Gold.ToVector3();
        public static Vector3 EndColor = Color.Red.ToVector3();

        float m_fTargetRadius;
        float m_fExpandRadius;
        float m_fContractionSpeed;
        float m_fExpansionSpeed;

        Wormhole m_InnerWormhole;
        Wormhole m_OuterWormhole;

        ShrinkingStarSphere(Game game, float radius, float contractionSpeed, float expansionSpeed)
            : base(game, radius, StarSphere.DefaultDensity)
        {
            // Initialize members.
            this.m_fTargetRadius = radius;
            this.m_fExpandRadius = 0f;
            this.m_fContractionSpeed = contractionSpeed;
            this.m_fExpansionSpeed = expansionSpeed;
        }

        public static ShrinkingStarSphere InitializeShrinkingStarSphere(Game game, float radius, float contractionSpeed, float expansionSpeed)
        {
            if (shrinkingStarSphere == null)
            {
                shrinkingStarSphere = new ShrinkingStarSphere(game, radius, contractionSpeed, expansionSpeed);
                game.Components.Add(shrinkingStarSphere);
            }
            return shrinkingStarSphere;
        }

        public void DestroyShrinkingStarSphere(Game game)
        {
            // Destroy all the stars.
            Dispose();

            // Destroy the wormholes.
            game.Components.Remove(m_InnerWormhole);
            game.Components.Remove(m_OuterWormhole);

            // Remove from game.
            game.Components.Remove(shrinkingStarSphere);

            // Drop the reference.
            shrinkingStarSphere = null;
        }

        public static ShrinkingStarSphere GetShrinkingStarSphere()
        {
            return shrinkingStarSphere;
        }

        public override void Update(GameTime gameTime)
        {
            // Determine target radius.
            if (!GameplayScreen.pause && !GameplayScreen.gameOver)
            {
                float targetRadius = (m_fExpandRadius == 0f) ? m_fTargetRadius : m_fExpandRadius;

                // Calculate new radius based on speed and target radius.
                if (m_fRadius > targetRadius)
                {
                    m_fRadius -= m_fContractionSpeed * GameplayScreen.fDelta;
                    if (m_fRadius <= targetRadius)
                    {
                        m_fRadius = targetRadius;
                        m_fExpandRadius = 0f;
                    }
                }
                else if (m_fRadius < targetRadius)
                {
                    m_fRadius += m_fExpansionSpeed * GameplayScreen.fDelta;
                    if (m_fRadius >= targetRadius)
                    {
                        m_fRadius = targetRadius;
                        m_fExpandRadius = 0f;
                    }
                }

                // Update color.
                m_StarColor = StartColor - ((StartColor - EndColor) * (1f - ((m_fRadius - LevelPlanetRadius) / (StartSize - LevelPlanetRadius))));

                base.Update(gameTime);
            }
        }

        /// <summary>
        /// Call this when you want the sphere to start shrinking.
        /// </summary>
        /// <param name="startRadius"></param>
        /// <param name="shrunkenRadius"></param>
        public void StartShrinking(float shrunkenRadius)
        {
            m_fTargetRadius = shrunkenRadius;
        }

        /// <summary>
        /// Call this when you want the sphere to start shrinking.
        /// </summary>
        /// <param name="startRadius"></param>
        /// <param name="shrunkenRadius"></param>
        public void StartShrinking(float startRadius, float shrunkenRadius)
        {
            m_fRadius = startRadius;
            m_fTargetRadius = shrunkenRadius;
        }

        /// <summary>
        /// Call this while to expand the star by deltaRadius amount.
        /// When it finishes expanding it will either stop or go back to shrinking if it was previously.
        /// </summary>
        /// <param name="deltaRadius"></param>
        public void Expand(float deltaRadius)
        {
            m_fExpandRadius = m_fRadius + deltaRadius;
        }

        /// <summary>
        /// This is called when the sphere finishes contracting.
        /// </summary>
        public bool IsFinishedContracting()
        {
            return (m_fRadius == m_fTargetRadius);
        }

        /// <summary>
        /// Create the wormholes for the sphere.
        /// </summary>
        public void CreateSphereWormholePair()
        {
            Tuple<Wormhole, Wormhole> wormholes = WormholeManager.GetWormholeManager().CreateWormholePair(0, 1.0f, 3.5f, 0.0f, 0.5f);
            m_InnerWormhole = wormholes.Item1;
            m_OuterWormhole = wormholes.Item2;

            // Set the angle toward the "fusion point"
            m_InnerWormhole.SetAngle(Vector3.UnitY);

            // Enlarge these wormholes.
            m_InnerWormhole.m_fScale = 2.5f;
            m_OuterWormhole.m_fScale = 2.5f;
        }
    }
}
